import os, shutil, sys
import os.path as osp
import time
import numpy as np
import pickle
import struct
import re
import cv2
from tqdm import tqdm
import imageio
import json
from tqdm import tqdm
import exifread
import random
import copy
from PIL import Image, ImageColor, ImageFont, ImageDraw, ImageFilter

from tool import filesystem, darknet_tool  # export PYTHONPATH=$PYTHONPATH:`pwd`

def random_crop_label_images(dataset_dir, 
                                save_dir = None,
                                max_shape=[2000, 2000], 
                                via_name="via_region_data.json", 
                                fill_other=False,
                                min_shape=[416, 416], 
                                crop_ratio=0., 
                                debug=False):
    """
    将标记框随机裁剪 生成新训练数据
    避免目标太小而检测不到

    @dataset_dir: 
        数据集根目录/子目录
    @max_height:
        裁剪图最大高
    @max_width:
        裁剪图最大宽
    @fill_other: bool
        是否用固定颜色填充别的roi, 只保留当前一个
    @min_wh:
        裁剪图片最小宽高 
    @crop_ratio:
        裁剪比例， 是否裁剪部分roi
    """

    via_files = filesystem.get_all_filepath(dataset_dir, [via_name])
    
    for via_file in via_files:
        with open(via_file) as f:
            label_infos = json.loads(f.read())
        
        print(via_file)
        image_dir = os.path.dirname(via_file)
        if save_dir:
            save_image_dir = osp.join(save_dir, image_dir.replace(dataset_dir+os.sep, ""))
        else:
            save_image_dir = image_dir + "_random_crop"
        os.makedirs(save_image_dir, exist_ok=True)
        write_dict = dict()

        for name in tqdm(label_infos.keys()):
            # if np.random.randint(5)  != 0:continue
            # print(label_infos[name]["filename"])
            cv_image = cv2.imread(image_dir + os.sep + label_infos[name]["filename"]) 
            h,w  = cv_image.shape[:2]
            fill_cv_image = copy.copy(cv_image)
            # print("h: {}, w: {}".format(h, w))

            rects = darknet_tool.__get_rects(label_infos[name], w, h)

            for idx,rect in enumerate(rects):
                random_crop_rect = _random_gen_crop_rect(rect, cv_image.shape, max_shape, min_shape, crop_ratio)
                if random_crop_rect[0] is None :continue
                if debug:
                    debug_filename =  "_{}.jpg".format(idx).join(label_infos[name]["filename"].split(".jpg"))
                    cv2.imwrite(save_image_dir + os.sep + debug_filename, cv_image[random_crop_rect[1]:random_crop_rect[1]+random_crop_rect[3], random_crop_rect[0]:random_crop_rect[0]+random_crop_rect[2] ] )

                all_save_rects = []
                if fill_other:
                    for oth_idx , oth_rect in enumerate(rects):
                        if oth_idx == idx: continue
                        w_iou, h_iou = iou_2(random_crop_rect, oth_rect)
                        if w_iou > 0 or h_iou > 0:
                            fill_cv_image[oth_rect[1]: oth_rect[1] + oth_rect[3], oth_rect[0]: oth_rect[0]+ oth_rect[2]] = np.mean(cv_image)
                    all_save_rects.append(rect)
                else:
                    ## check other rect
                    apply_all = True
                    count = 0
                    while apply_all and count < 10:
                        count += 1
                        for oth_idx,every_rect in enumerate(rects):
                            w_iou, h_iou = iou_2(random_crop_rect, every_rect)
                            # print(w_iou, "   " , h_iou)

                            if h_iou == 1.0 and w_iou == 1.0:
                                all_save_rects.append(every_rect)
                                apply_all = False
                            elif 0<h_iou<1  or 0<w_iou <1:      # 判断是否与其它rect有部分重叠， 并且修正
                                apply_all = True
                                all_save_rects = []
                                
                                nx,ny,nw,nh,_ = random_crop_rect
                                if 0<w_iou <1 and random_crop_rect[0] > every_rect[0]:
                                    nx = every_rect[0] 
                                if 0<w_iou <1 and random_crop_rect[0] < every_rect[0]:
                                    nw = nw + (every_rect[0] + every_rect[2] - random_crop_rect[0] - random_crop_rect[2] )

                                if 0<h_iou <1 and random_crop_rect[1] > every_rect[1]:
                                    ny = every_rect[1]
                                if 0<h_iou <1 and random_crop_rect[1] < every_rect[1]:
                                    nh = nh + (every_rect[1] + every_rect[1] - random_crop_rect[1] - random_crop_rect[1] )
                                  
                                random_crop_rect = [
                                                        nx,
                                                        ny,
                                                        w - nx if nx + nw > w else nw,
                                                        h - ny if ny + nh > h else nh,
                                                        random_crop_rect[4]
                                ]
                                break
                if len(all_save_rects ) == 0:continue
                
                filename =  "_{}.jpg".format(idx).join(label_infos[name]["filename"].split(".jpg"))
                save_image_path = save_image_dir + os.sep + filename
                if not debug:
                    # print(random_crop_rect)
                    cv2.imwrite(save_image_path, fill_cv_image[random_crop_rect[1]:random_crop_rect[1]+random_crop_rect[3], random_crop_rect[0]:random_crop_rect[0]+random_crop_rect[2] ] )
                if fill_other: fill_cv_image = copy.copy(cv_image)
                
                k,v = __build_region_data(all_save_rects, save_image_path, diff_rect=random_crop_rect)
                write_dict[k] = v
            
            if len(rects) == 0:
                rect_param = [[0.3,0.3],[0.6,0.3],[0.6,0.6],[0.3,0.6]]
                for idx in range(4):
                    rect = rect_param[idx] + [20,20]
                    random_crop_rect = _random_gen_crop_rect(rect, cv_image.shape, max_shape, min_shape, crop_ratio)
                    if random_crop_rect[0] is None :continue
                    
                    filename =  "_{}.jpg".format(idx).join(label_infos[name]["filename"].split(".jpg"))
                    save_image_path = save_image_dir + os.sep + filename
                    if not debug:
                        print(random_crop_rect)
                        cv2.imwrite(save_image_path, fill_cv_image[random_crop_rect[1]:random_crop_rect[1]+random_crop_rect[3], random_crop_rect[0]:random_crop_rect[0]+random_crop_rect[2] ] )
                    if fill_other: fill_cv_image = copy.copy(cv_image)
                    
                    k,v = __build_region_data(all_save_rects, save_image_path, diff_rect=random_crop_rect)
                    write_dict[k] = v

        with open(save_image_dir + os.sep + via_name, "w", encoding="utf8" ) as wf:
            wf.write(json.dumps(write_dict) )



def __build_region_data(all_save_rects, save_image_path, diff_rect=None):
    return_data = dict()
    file_size = osp.getsize(save_image_path)
    filename = osp.basename(save_image_path)
    return_data["filename"] = filename
    return_data["size"] = file_size
    
    regions = []
    for rect in all_save_rects:
        region = dict()

        region["region_attributes"] = {"label": rect[4]}
        ## 判断是否超出边界
        if rect[0] - diff_rect[0] < 0 :
            x = 2 
            w = rect[2] +    rect[0] - diff_rect[0] 
        else :
            x = rect[0] - diff_rect[0]
            w = rect[2]
        
        if rect[1] - diff_rect[1] < 0:
            y = 2 
            h = rect[3] + rect[1] - diff_rect[1]
        else:
            y = rect[1] - diff_rect[1]
            h = rect[3]
        

        # if x <0 or y < 0:
        #     continue
        region["shape_attributes"] = {"name": "rect",
                                        "x": x,
                                        "y": y,
                                        "width": diff_rect[2] - x - 2 if x + w > diff_rect[2] else w,
                                        "height": diff_rect[3] - y -2 if y + h > diff_rect[3] else h
                                    
                                    }
        regions.append(region)
    return_data["regions"] = regions
    return_data["file_attributes"] = {}

    return filename+str(file_size), return_data

def _random_gen_crop_rect(rect, img_shape, max_shape, min_shape, crop_ratio=0):
    """
    `random_crop_label_images` implement
    near to square
    @crop_ratio: float
        裁剪比例， 是否裁剪部分roi
    """
    min_shape = [max(rect[3] , min_shape[0]), max(rect[2] , min_shape[1])]

    if min_shape[1] > min(img_shape[1], max_shape[1]): return [None] * 5
    if min_shape[0] > min(img_shape[0], max_shape[0]): return [None] * 5

    dst_width = np.random.randint(min_shape[1], min(img_shape[1], max_shape[1]) )

    start_x = max(rect[0] + rect[2] - dst_width - int(crop_ratio * rect[2]) , 0)
    end_x = min(rect[0] + int(crop_ratio * rect[2]) , img_shape[1] - dst_width)
    
    if start_x >= end_x:
        return [None] * 5
    sx = np.random.randint(start_x, end_x)

    dst_height = np.random.randint(min_shape[0], min(img_shape[0], max_shape[0]))
    start_y = max(rect[1] + rect[3] - dst_height - int(crop_ratio * rect[3]), 0)
    end_y = min(rect[1] + int(crop_ratio * rect[3]), img_shape[0] - dst_height)
    if start_y >= end_y:
        return [None] * 5
    sy = np.random.randint(start_y, end_y)

    return [sx,sy,dst_width, dst_height, rect[4]]

# from tool import opencv_tool # export PYTHONPATH=$PYTHONPATH:`pwd`
def vconcatenate_image(a, b, distance):
    """
    竖直连接 a, b 图片. 间距为 distance
    
    """
    diff_width = abs(a.shape[1]- b.shape[1])
    if a.shape[1] <  b.shape[1]:

        aa = cv2.copyMakeBorder(a,
                                0,
                                0, 
                                0, 
                                diff_width, 
                                cv2.BORDER_CONSTANT,
                                None,
                                [255,255,255])
        bb = b

    elif a.shape[1] >=  b.shape[1]:

        aa = a
        bb = cv2.copyMakeBorder(b,
                                0 ,
                                0, 
                                0, 
                                diff_width, 
                                cv2.BORDER_CONSTANT,
                                None,
                                [255,255,255])
    if distance != 0:
        diff = np.ones((distance, aa.shape[1]), dtype=np.uint8) * 255
        temp_img = np.concatenate((aa,diff, bb), axis=0)
    else:
        temp_img = np.concatenate((aa, bb), axis=0)

    return temp_img

def hconcatenate_image(a, b, distance):
    """
    水平连接 a, b 图片. 间距为 distance
    前面小放在上面，后面小放在中间，便于不改变标记数据
    """
    diff_height = abs(a.shape[0]- b.shape[0])
    if a.shape[0] <  b.shape[0]:

        aa = cv2.copyMakeBorder(a,
                                0,
                                diff_height, 
                                0, 
                                0, 
                                cv2.BORDER_CONSTANT,
                                None,
                                [255,255,255])
        bb = b

    elif a.shape[0] >=  b.shape[0]:

        aa = a
        bb = cv2.copyMakeBorder(b,
                                0 ,
                                diff_height, 
                                0, 
                                0, 
                                cv2.BORDER_CONSTANT,
                                None,
                                [255,255,255])
    if distance != 0:
        diff = np.ones((aa.shape[0], distance), dtype=np.uint8)  * 255
        temp_img = np.concatenate((aa,diff, bb), axis=1)
    else:
        temp_img = np.concatenate((aa, bb), axis=1)

    return temp_img

def hconcatenate_image_2(a, b, distance, return_box=False):
    """
    水平连接 a, b 图片. 间距为 distance
    前面小放在上面，后面小放在中间，便于不改变标记数据
    """
    max_height = abs(a.shape[0]- b.shape[0])
    if a.shape[0] <  b.shape[0]:
        top = 0
        aa = cv2.copyMakeBorder(a,
                                top,
                                b.shape[0] - a.shape[0], 
                                0, 
                                0, cv2.BORDER_CONSTANT)
        bb = b

    elif a.shape[0] >=  b.shape[0]:
        top = max_height // 2 if max_height % 2 == 0 else max_height // 2 +1
        aa = a
        bb = cv2.copyMakeBorder(b,
                                top ,
                                max_height // 2, 
                                0, 
                                0, cv2.BORDER_CONSTANT)
    diff = np.zeros((aa.shape[0], distance), dtype=np.uint8) 
    temp_img = np.concatenate((aa,diff, bb), axis=1)
    if return_box:
        box = [
                [a.shape[1] + distance, top],
                [a.shape[1] + distance + b.shape[1], top],
                [a.shape[1] + distance + b.shape[1], top+b.shape[0] ] ,
                [a.shape[1] + distance , top+b.shape[0]] 
            ]
        return temp_img, box
    else:
        return temp_img

def points_sort(points):
    """
        @points: [[x,y],[x,y],...]
        将矩形四个点按照顺时针方向排序    
    """
    new_points = [0,0,0,0]
    x_sorted_ps = sorted(points, key=lambda x: x[0])
    if x_sorted_ps[0][1] < x_sorted_ps[1][1]:
        new_points[0] = x_sorted_ps[0]
        new_points[3] = x_sorted_ps[1]
    else:
        new_points[0] = x_sorted_ps[1]
        new_points[3] = x_sorted_ps[0]
    
    if x_sorted_ps[2][1] < x_sorted_ps[3][1]:
        new_points[1] = x_sorted_ps[2]
        new_points[2] = x_sorted_ps[3]
    else:
        new_points[1] = x_sorted_ps[3]
        new_points[2] = x_sorted_ps[2]    
    return new_points

def resize_image_fix_height(cv_img,fixed_height):
    """
    将图片缩放到固定高
    """
    height = cv_img.shape[0]
    width = cv_img.shape[1]
    ratio = fixed_height / height
    resize_h = fixed_height
    resize_w = width * ratio
    interpolation = cv2.INTER_AREA if height > fixed_height else cv2.INTER_LINEAR
    cv_img = cv2.resize(cv_img, (int(resize_w), resize_h),cv_img,0.,0., interpolation)
    return cv_img

def pad_image_width(cv_img, target_width):
    cv_img =cv2.copyMakeBorder(cv_img,0,0,0,target_width-cv_img.shape[1], cv2.BORDER_CONSTANT,cv_img, [255] )
    return cv_img


def letterbox_image_pil(image, std_w, std_h):
    '''
    resize image with unchanged aspect ratio using padding
    Reference: https://github.com/qqwweee/keras-yolo3/blob/master/yolo3/utils.py
    '''
    image_w, image_h = image.size
    
    # if max(image_w, image_h) < min(size):
    if image_w <= std_w and image_h <= std_h:
        resized_image = image
        new_w = std_w
        new_h = std_h
    else:
        new_w = int(image_w * min(std_w*1.0/image_w, std_h*1.0/image_h))
        new_h = int(image_h * min(std_w*1.0/image_w, std_h*1.0/image_h))
        resized_image = image.resize((new_w,new_h), Image.BICUBIC)
    
    boxed_image = Image.new('L', (std_w, std_h), (128 ))
    # boxed_image.paste(resized_image, ((w-new_w)//2, (h-new_h)//2))
    boxed_image.paste(resized_image, (0, 0))
    return boxed_image


def letterbox_image_cv(image, std_w, std_h):
    '''
    resize image with unchanged aspect ratio using padding
    Reference: https://github.com/qqwweee/keras-yolo3/blob/master/yolo3/utils.py
    '''
    if len(image.shape) == 2:
        image_h, image_w = image.shape
        channel = 1
    elif len(image.shape) == 3:
        image_h, image_w, channel = image.shape
    else:
        raise NotImplementedError

    # if max(image_w, image_h) < min(size):
    if image_w <= std_w and image_h <= std_h:
        resized_image = image
        new_w = std_w
        new_h = std_h
    else:
        new_w = int(image_w * min(std_w*1.0/image_w, std_h*1.0/image_h))
        new_h = int(image_h * min(std_w*1.0/image_w, std_h*1.0/image_h))
        resized_image = cv2.resize(image, (new_w,new_h), cv2.INTER_CUBIC)
    
    boxed_image = cv2.copyMakeBorder(resized_image, 
                                    (std_h - image_h) // 2 if (std_h - image_h) % 2 == 0 else (std_h - image_h) // 2 +1,
                                    (std_h - image_h) // 2,
                                    (std_w - image_w) // 2 if (std_w - image_w) % 2 == 0 else (std_w - image_w) // 2 + 1,
                                    (std_w - image_w) // 2,
                                    cv2.BORDER_CONSTANT, 
                                    [255] if channel == 1 else [255, 255, 255])
    return boxed_image

def point_in_rect(p, rect):
    return rect[0] < p[0] < rect[0] + rect[2] \
        and rect[1] < p[1] < rect[1] + rect[3]
        
def iou(rect1, rect2):
    y0 = np.max([rect1[1],rect2[1]])
    y1 = np.min([rect1[1] + rect1[3],rect2[1]+rect2[3]])

    x0 = np.max([rect1[0],rect2[0]])
    x1 = np.min([rect1[0] + rect1[2],rect2[0]+rect2[2]])
    return x1 > x0 and y1 > y0

def iou_3(rect1, rect2):
    y0 = np.max([rect1[1],rect2[1]])
    y1 = np.min([rect1[1] + rect1[3],rect2[1]+rect2[3]])

    x0 = np.max([rect1[0],rect2[0]])
    x1 = np.min([rect1[0] + rect1[2],rect2[0]+rect2[2]])
    if x1 > x0 and y1 > y0:
        ratio = (x1 - x0) * (y1 - y0) / (min(rect1[2], rect2[2]) * min(rect1[3], rect2[3]))
    else:
        ratio = -1
    return ratio, [x0, y0, x1 - x0, y1 - y0]
    

def iou_2(rect1, rect2):
    """
    判断两个矩形是否完全包含, 返回宽高的重叠度
    """
    y0 = np.max([rect1[1],rect2[1]])
    y1 = np.min([rect1[1] + rect1[3],rect2[1]+rect2[3]])

    x0 = np.max([rect1[0],rect2[0]])
    x1 = np.min([rect1[0] + rect1[2],rect2[0]+rect2[2]])

    if y1 - y0 == np.min([rect1[3],rect2[3]]):
        h_iou = 1
    elif  y1 - y0 > 0:
        h_iou = (y1 - y0) / np.min([rect1[3],rect2[3]])
    else:
        h_iou = 0

    if x1 - x0 == np.min([rect1[2],rect2[2]]):
        w_iou = 1
    elif  x1 - x0  > 0:
        w_iou = (x1 - x0) / np.min([rect1[2],rect2[2]])
    else:
        w_iou = 0

    return w_iou, h_iou

def enlarge_contours_border(region, region_type="rect", border_shape=[0,0], dilate_ratio=2.0):
    """
        扩大轮廓边框
        用于样本生成时，防止元素与元素发生掩码区域重叠
        @region: "坐标区域 [[x,y],[],...]" , 外围矩形框
        @region_type: "polygon", "rect"
    """
    region = np.array(region)
    whole_mask = np.zeros(border_shape, dtype=np.uint8)
    new_mask = cv2.fillConvexPoly(whole_mask, region, [255])

    roi_width = (dilate_ratio - 1) * (np.max(region[:, 0]) - np.min(region[:, 0]))
    roi_height = (dilate_ratio - 1) * (np.max(region[:, 1]) - np.min(region[:, 1]))
    roi_width = int(roi_width)
    roi_height = int(roi_height)

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, 
        (np.min([roi_width, roi_height]) , np.min([roi_width, roi_height])))  # 矩形结构
    dilate_mask = cv2.dilate(new_mask, kernel)
    
    contours, hierarchy = cv2.findContours(dilate_mask,cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    if region_type == "polygon":
        return contours[0]
    elif region_type == "rect":
        rect = cv2.boundingRect(contours[0])
        
        return np.array([[rect[0], rect[1]],
                            [rect[0]+ rect[2], rect[1]],
                            [rect[0]+ rect[2], rect[1]+rect[3]],
                            [rect[0], rect[1]+rect[3]]])
    else:
        raise NotImplementedError
    
def resize_img(dir_path, w=0, h=0):
    total_files= filesystem.get_all_filepath(dir_path, [".jpg", ".png"])
    for f in total_files:
        cv_image = cv2.imread(f)
        rw = cv_image.shape[1] // 2 if w == 0 else w
        rh = cv_image.shape[0] // 2 if h == 0 else h
        cv_image = cv2.resize(cv_image, (rw, rh))

        cv2.imwrite(f, cv_image)


def cv_warp_perspective(img, language=None, max_x_ratio=0.5, max_y_ratio=1):
    """ 使图像轻微的畸变
        img 输入图像, pil_image
        factor 畸变的参数
        size 为图片的目标尺寸
    """
    final_image = img.convert('RGBA')
    final_image_cv = np.array(final_image)
    cv_image = final_image_cv[:,:,:3]

    alpha = final_image_cv[:,:,-1]
    size_o = [cv_image.shape[1],cv_image.shape[0]]
    # print size_o
    # size = (shape[1]+ int(shape[0]*cos((float(max_angel )/180) * 3.14)),shape[0])
    # print size
    # size = (shape[1]+ int(shape[0]*sin((float(max_angel )/180) * 3.14)),shape[0])
    # # print size
    # interval = abs( int( sin((float(angel) /180) * 3.14)* shape[0]));

    pts1 = np.float32([[0,0],[size_o[0],0],[size_o[0],size_o[1]],[0,size_o[1]]])
    
    if language == "shuxian_1":
        # 上下左右移动的偏移值
        x_diff = np.random.randint(10,25) 
        y_diff = 0

        # change right

        p1 = [x_diff, 0]
        p2 = [
            size_o[0]+x_diff ,
                0  
                ]
        p3 = [
            size_o[0],
                size_o[1]  
        ]
        p4 =[
            0,
            size_o[1] 
        ]
        pts2 = np.float32([p1,p2,p3,p4])
    elif language == "shuxian_2" or language == "shuxian_3":
        # 向左向右偏移值
        x_diff = np.random.randint(40) - 20 
        y_diff = 0

        # change right

        p1 = [
            0 if x_diff < 0 else x_diff, 
            0
        ]
        p2 = [
            size_o[0] if x_diff < 0 else size_o[0] + x_diff,
                0  
                ]
        p3 = [
            size_o[0]+ (-x_diff)  if x_diff < 0 else size_o[0],
                size_o[1]  
        ]
        p4 =[
            -x_diff if x_diff < 0 else 0,
            size_o[1] 
        ]
        pts2 = np.float32([p1,p2,p3,p4])
    elif language == "driving_license":
        # 上下左右移动的偏移值
        x_offset = np.random.randint(-6,6) 
        y_diff = 0


        p1 = [0 if x_offset <0 else x_offset, 0]
        p2 = [
                size_o[0] if x_offset < 0 else size_o[0] + x_offset,
                0  
            ]
        p3 = [
            size_o[0]-x_offset if x_offset < 0 else size_o[0],
            size_o[1]  
        ]
        p4 =[
            0-x_offset if x_offset <0 else 0,
            size_o[1] 
        ]
        pts2 = np.float32([p1,p2,p3,p4])
    
    else:
        x_diff = int(size_o[0] * np.random.random() *max_x_ratio )
        y_diff = int(size_o[1] * np.random.random() *max_y_ratio )
        if np.random.randint(2) < 1:
            # change left
            x_diff = -x_diff if np.random.randint(2) < 1 else x_diff
            y_diff = -y_diff if np.random.randint(2) < 1 else y_diff
            p1 = [0, 0 if y_diff < 0 else y_diff]
            p2 = [size_o[0]-x_diff if x_diff < 0 else size_o[0]-x_diff,
                    -y_diff  if y_diff < 0  else 0]
            p3 = [
                size_o[0]-x_diff if x_diff < 0 else size_o[0]-x_diff,
                size_o[1]-y_diff  if y_diff < 0  else size_o[1]
            ]
            p4 =[
                0,
                0 + size_o[1] if y_diff < 0 else y_diff + size_o[1]
            ]
            pts2 = np.float32([p1,p2,p3,p4])
        else:
            # change right
            x_diff = -x_diff if np.random.randint(2) < 1 else x_diff
            y_diff = -y_diff if np.random.randint(2) < 1 else y_diff
            p1 = [0, -y_diff if y_diff < 0 else 0]
            p2 = [
                size_o[0]+x_diff if x_diff < 0 else size_o[0]+x_diff,
                    0  if y_diff < 0  else y_diff
                    ]
            p3 = [
                size_o[0]+x_diff if x_diff < 0 else size_o[0]+x_diff,
                    0+size_o[1]  if y_diff < 0  else y_diff+size_o[1]
            ]
            p4 =[
                0,
                size_o[1] -y_diff if y_diff < 0 else  size_o[1]
            ]
            pts2 = np.float32([p1,p2,p3,p4])


    M  = cv2.getPerspectiveTransform(pts1,pts2)
    max_x ,max_y= np.max(pts2,axis=0 )

    dst = cv2.warpPerspective(cv_image,M,(max_x, max_y))
    mask = cv2.warpPerspective(alpha,M,(max_x, max_y))
    return dst, mask, pts2
    
def remove_image_by_size(data_dir):
    def remove_image_mean(data_dir):
        files = filesystem.get_all_filepath(data_dir, [".jpg"])
        for f in files:
            # print(os.path.getsize(f))
            if os.path.getsize(f) < 2100:
                print(f)
                shutil.move(f, "/home/swls/Desktop/1/" + os.path.basename(f))
            # image = cv2.imread(f, 1)
            # image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY   )
            # image_gray = cv2.blur(image_gray, (5,5))

            # img_BGR_mean =cv2.meanStdDev(image[:,image.shape[1] // 4 :image.shape[1] // 2])

            # img_mean =cv2.meanStdDev(image_gray[:,image_gray.shape[1] // 4 :image_gray.shape[1] // 2])
            # print(img_BGR_mean, img_mean)
    
    remove_image_mean(data_dir)

def remove_image_by_min_shape(data_dir):
    total_files = filesystem.get_all_filepath(data_dir, [".jpg"])
    for f in tqdm(total_files):
        img = cv2.imread(f)
        h, w = img.shape[:2]
        if h < 32 or w < 32:
            os.remove(f)

def remove_image_by_mean(data_dir, min_times=1e2, recursive=-1):
    last_dirs = filesystem.get_last_dir(data_dir, recursive)

    for last_dir in last_dirs:
        files = filesystem.get_all_filepath(last_dir, [".jpg"])
        mean_dict = {}

        for f in files:
            img = cv2.imread(f)
            mean = np.mean(img)
            mean = int(mean * min_times)
            if mean_dict.get(mean, None): continue
            mean_dict[mean] = True
            mean_dict[f] = True

        for f in files:
            if mean_dict.get(f, None): continue
            print("remove: ", f)
            os.remove(f)

def rgb_to_gray(img_path):
    img = cv2.imread(img_path)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    save_path = img_path.replace(".jpg", "_gray.jpg")
    cv2.imwrite(save_path, gray_img)


def read_and_save_jpg(data_dir):
    imgs = filesystem.get_all_filepath(data_dir)
    for idx, f in enumerate(imgs):
        img = cv2.imread(f)
        # img = cv2.resize(img, (img.shape[1] // 2, img.shape[0] // 2))

        save_path = osp.join(osp.dirname(f), "resize_" + osp.basename(f) + ".jpg")
        cv2.imwrite(save_path, img)
        # os.remove(f)


def read_exif_info(img_path):
    f = open(img_path,"rb")
    tags = exifread.process_file(f)
    for k, v in tags.items():
        print(k, v)

def concat_img(data_dir):
    imgs = filesystem.get_all_filepath(data_dir, [".jpg"])
    imgs = sorted(imgs)

    img = None
    for f in imgs:
        cur_img = cv2.imread(f)
        if img is None:
            img = cur_img
        else :
            img = hconcatenate_image(img, cur_img, 0)
    cv2.imwrite(data_dir+".jpg", img)

def rotate_img(img_path, angle):
    image = Image.open(img_path)
    image = image.rotate(angle, fillcolor=(255,255,255))
    image.save(img_path)

if __name__ == "__main__":
    # dir_path = sys.argv[1]
    # dir_path= "/mnt/disk1/vanlance/project/plate_recognition/font/template_yellow_double2"
    # resize_img(dir_path, 1280, 675)


    # data_dir = sys.argv[1]
    # concat_img(data_dir)

    # data_dir = sys.argv[1]
    # remove_image_by_size(data_dir)

    # data_dir = sys.argv[1]
    # rgb_to_gray(data_dir)

    # f = "/home/xc/Downloads/2021-07-04 05-56-38.png"
    # cv_image = cv2.imread(f)
    # cv2.imshow("aa", cv_image)
    # cv2.waitKey(0)

    # data_dir = sys.argv[1]
    # remove_image_by_min_shape(data_dir)
    # pass

    # data_dir = sys.argv[1]
    # last_dirs = filesystem.get_last_dir(data_dir, 0)
    # for d in last_dirs:
    #     remove_image_by_mean(d, 1e4, 0)


    # data_dir = sys.argv[1]
    # remove_image_by_mean(data_dir, 1e4, 0)

    # data_dir = sys.argv[1]
    # read_and_save_jpg(data_dir)

    # img_path = sys.argv[1]
    # read_exif_info(img_path)


    data_dir = r"F:\work\dataset\det\rgl\dataset\images"
    # save_dir = data_dir +"_deal"
    # if not osp.exists(save_dir):
    #     os.makedirs(save_dir, exist_ok=True)
    for p in filesystem.get_all_filepath(data_dir, [".jpg"]):
        img = cv2.imread(p)
        cv2.imwrite(p, img)
    
    # img_path = sys.argv[1]
    # rotate_img(img_path, -5)


    # img = cv2.imread("F:\\work\\code\\b8ae18f2b3059923c5f6555fd88bd12.png", cv2.IMREAD_UNCHANGED)
    # # imgs = cv2.split(img)
    # # print(imgs[0])
    # # print(imgs[1])
    # hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    # hsvs = cv2.split(hsv)
    # print(cv2.meanStdDev(hsv[0]))
    # print(cv2.meanStdDev(hsv[1]))
    # print(cv2.meanStdDev(hsv[2]))
    # print(hsv.shape)
